package com.cyy.learn.javaFxXmlToObjectCode

import javafx.beans.property.SimpleStringProperty
import tornadofx.*
import com.cyy.util.StrUtil
import org.dom4j.DocumentHelper
import org.dom4j.Element


val strFxml=SimpleStringProperty("")
val strController=SimpleStringProperty("")
val strView=SimpleStringProperty("")
val strService=SimpleStringProperty("")
class JavaFxXmlToObjectCode:View("JavaFxXmlToObjectCode") {
    val C:JavaFxXmlToObjectCodeController by inject()
    override val root=borderpane{
        top=hbox {
            button("转换为code") {
                action {
                    val strArray=C.xmlToCode(strFxml.value)
                    strController.value=strArray[0]
                    strView.value=strArray[1]
                    strService.value=strArray[2]
                }
            }
        }
        center=hbox(10) {

            textarea(strFxml) {
                promptText="请输入fxml"
            }
            textarea(strController) {
                promptText="生成的Controller Bean代码"
            }
            textarea(strView) {
                promptText="生成的View Bean代码"
            }
            textarea(strService) {
                promptText="生成的Service Bean代码"
            }
        }
    }
}

class JavaFxXmlToObjectCodeController:Controller(){
    val strList= mutableListOf<String>()
    @Throws(Exception::class)
    fun xmlToCode(xmlStr: String): Array<String> {
        val attrStrBuilder = StringBuilder()// 创建属性值获取
        val funStrBuilder = StringBuilder()// 创建方法值获取
        val classNameStrBuilder = StringBuilder()// 创建类值获取
        val document = DocumentHelper.parseText(xmlStr)
        val root = document.rootElement
        attrStrBuilder.append("\n").append("""override val root= ${root.name.toLowerCase()}{""")
        getCodeByElement(root, attrStrBuilder, funStrBuilder, classNameStrBuilder)
        val packageString = classNameStrBuilder.toString().split("controller".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()

        val packageStringSplit = packageString[1].split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
        val classNameString = packageStringSplit[packageStringSplit.size - 1].split("Controller".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0]
        val classNameStringLoCase = StrUtil.fristToLoCase(classNameString)
        val viewPackage = packageString[1].substring(0, packageString[1].lastIndexOf("."))

        val controllerClassStrBuilder = StringBuilder()//控制层类字符串
//        controllerClassStrBuilder.append("package com.xwintop.xJavaFxTool.controller$viewPackage;\n")
//        controllerClassStrBuilder.append("import com.xwintop.xJavaFxTool.view" + viewPackage + "." + classNameString + "View;\n")
//        controllerClassStrBuilder.append("import com.xwintop.xJavaFxTool.services" + viewPackage + "." + classNameString + "Service;\n")
//        controllerClassStrBuilder.append("import lombok.Getter;\n")
//        controllerClassStrBuilder.append("import lombok.Setter;\n")
//        controllerClassStrBuilder.append("import lombok.extern.slf4j.Slf4j;\n")
//        controllerClassStrBuilder.append("import java.net.URL;\n")
//        controllerClassStrBuilder.append("import java.util.ResourceBundle;\n")
//        controllerClassStrBuilder.append("import javafx.event.ActionEvent;\n")
//        controllerClassStrBuilder.append("import javafx.fxml.FXML;\n")
//        controllerClassStrBuilder.append("@Getter\n@Setter\n@Slf4j\n")
//        controllerClassStrBuilder.append("public class " + classNameString + "Controller extends " + classNameString + "View {\n")

        // generator tornadofx Controller
        controllerClassStrBuilder.append("import tornadofx.*\n")
        controllerClassStrBuilder.append("class ${classNameString}Controller : Controller() {\n")

//        controllerClassStrBuilder.append("private " + classNameString + "Service " + classNameStringLoCase + "Service = new " + classNameString + "Service(this);\n")
        //		@Override
        //		public void initialize(URL location, ResourceBundle resources) {
        //		}
//        controllerClassStrBuilder.append("\n@Override\npublic void initialize(URL location, ResourceBundle resources) {\n")
//        controllerClassStrBuilder.append("initView();\n")
//        controllerClassStrBuilder.append("initEvent();\n")
//        controllerClassStrBuilder.append("initService();\n")
//        controllerClassStrBuilder.append("}")
//        controllerClassStrBuilder.append("\n private void initView() {}")
//        controllerClassStrBuilder.append("\n private void initEvent() {}")
//        controllerClassStrBuilder.append("\n private void initService() {}")
        controllerClassStrBuilder.append(funStrBuilder.toString())
        controllerClassStrBuilder.append("}")


        val classStrBuilder = StringBuilder()//视图view类字符串
//        classStrBuilder.append("package com.xwintop.xJavaFxTool.view$viewPackage;\n")
//        classStrBuilder.append("import lombok.Getter;\n")
//        classStrBuilder.append("import lombok.Setter;\n")
//        classStrBuilder.append("import javafx.fxml.Initializable;\n")
//        classStrBuilder.append("import javafx.fxml.FXML;\n")
//        val importList = document.content()
//        for (node in importList) {
//            if ("import" == node.name) {
//                classStrBuilder.append("import " + node.text + ";\n")
//            }
//        }
//        classStrBuilder.append("@Getter\n@Setter\n")
//        classStrBuilder.append("public abstract class " + classNameString + "View implements Initializable {\n")

        // generator tornadofx view

        classStrBuilder.append("import javafx.beans.property.SimpleStringProperty\n")
        classStrBuilder.append("import tornadofx.*\n")

        strList.forEach{
            classStrBuilder.append(it)
        }
        classStrBuilder.append("\nclass ${classNameString}View : View(\"${classNameString}\") {\n")
        classStrBuilder.append("val C: ${classNameString}Controller by inject()\n")
        classStrBuilder.append(attrStrBuilder.toString())
        classStrBuilder.append("\n}")

        val serviceClassStrBuilder = StringBuilder()//控制层类字符串
        serviceClassStrBuilder.append("package com.xwintop.xJavaFxTool.services$viewPackage;\n")
        serviceClassStrBuilder.append("import com.xwintop.xJavaFxTool.controller" + viewPackage + "." + classNameString + "Controller;\n")
        serviceClassStrBuilder.append("import lombok.Getter;\n")
        serviceClassStrBuilder.append("import lombok.Setter;\n")
        serviceClassStrBuilder.append("import lombok.extern.slf4j.Slf4j;\n")
        serviceClassStrBuilder.append("@Getter\n@Setter\n@Slf4j\n")
        serviceClassStrBuilder.append("public class " + classNameString + "Service{\n")
        serviceClassStrBuilder.append("private " + classNameString + "Controller " + classNameStringLoCase + "Controller;\n")
        serviceClassStrBuilder.append("public " + classNameString + "Service(" + classNameString + "Controller " + classNameStringLoCase + "Controller) {\n")
        serviceClassStrBuilder.append("this." + classNameStringLoCase + "Controller = " + classNameStringLoCase + "Controller;\n}\n")
        serviceClassStrBuilder.append("}")

        return arrayOf(controllerClassStrBuilder.toString(), classStrBuilder.toString(), serviceClassStrBuilder.toString())
    }

    private fun getCodeByElement(root: Element, attrStrBuilder: StringBuilder, funStrBuilder: StringBuilder, classNameStrBuilder: StringBuilder) {
        val rootAttrList = root.attributes()
        for (rootAttr in rootAttrList) {
            when(rootAttr.name) {
                "id" -> {
                    if(root.name in listOf("TextArea","TextField","Text")){
                        strList.add("""val ${rootAttr.value}=SimpleStringProperty("")${"\n"}""")
                        attrStrBuilder.append("\n").append("""${root.name.toLowerCase()}(${rootAttr.value}){promptText="${root.attribute("promptText")?.value}"}""")
                    }
                    if(root.name in listOf("ChoiceBox")){
                        strList.add("""val ${rootAttr.value}=SimpleStringProperty()${"\n"}""")
                        strList.add("""val ${rootAttr.value}s=listOf("")${"\n"}""")

                        attrStrBuilder.append("\n").append("""${root.name.toLowerCase()}(${rootAttr.value},${rootAttr.value}s)""")
                    }
                    if(root.name in listOf("ColorPicker")){
                        strList.add("""val ${rootAttr.value}=SimpleObjectProperty(Color.BLACK)${"\n"}""")
                        attrStrBuilder.append("\n").append("""${root.name.toLowerCase()}(${rootAttr.value})""")
                    }
                    if(root.name in listOf("Slider")){
                        attrStrBuilder.append("\n").append("""${root.name.toLowerCase()}()""")
                    }
                    if(root.name in listOf("ImageView")){
                        strList.add("""lateinit var ${rootAttr.value}: ImageView${"\n"}""")
                        attrStrBuilder.append("\n").append("""${root.name.toLowerCase()}{
                            |fitHeight=${root.attribute("fitHeight")?.value?.toDouble()}
                            |fitHeight=${root.attribute("fitHeight")?.value?.toDouble()}
                            |isPickOnBounds=${root.attribute("pickOnBounds")?.value?.toBoolean()}
                            |isPreserveRatio=${root.attribute("preserveRatio")?.value?.toBoolean()}
                            |}""".trimMargin())
                    }


                }
                "onAction"-> {
                    //				@FXML
                    //				private void xmlToSql(ActionEvent event){}
//                    funStrBuilder.append("\n@FXML\nprivate void ")
//                    funStrBuilder.append(rootAttr.value.substring(1)).append("(ActionEvent event){\n}\n")

                    // generator tornadofx Controller fun
                    funStrBuilder.append("fun ${rootAttr.value.substring(1)}(){\n}").append("\n")
                }
                "controller" -> classNameStrBuilder.append(rootAttr.value)
            }
        }

        root.elements().forEach{
            if(it.name in listOf("AnchorPane","BorderPane","ScrollPane","TabPane","GridPane","TitledPane","Tab","center","top","HBox","VBox")){
                attrStrBuilder.append("\n").append("""}${"\n"}${it.name.toLowerCase()}{""".trimMargin())
            }
            if(it.name in listOf("Label")){
                attrStrBuilder.append("\n").append("""${it.name.toLowerCase()}("${it.attribute("text")?.value}")""")
            }
            if(it.name in listOf("CheckBox")){
                attrStrBuilder.append("\n").append("""${it.name.toLowerCase()}("${it.attribute("text")?.value}"){isSelected=true}""")
            }
            if(it.name in listOf("Button")){
                attrStrBuilder.append("\n").append("""${it.name.toLowerCase()}("${it.attribute("text")?.value}"){
                            |action{
                            |   C.${it.attribute("onAction").value.substring(1)}()
                            |}
                            |}""".trimMargin())}

            getCodeByElement(it, attrStrBuilder, funStrBuilder, classNameStrBuilder)
        }
    }
}